package com.example.access_control.AccessControl;


import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.access_control.AccessControl.Acs.AcsMain;
import com.example.access_control.AccessControl.Acs.TransIsapi;
import com.example.access_control.AccessControl.Commom.ConfigFileUtil;
import com.example.access_control.AccessControl.Commom.osSelect;
import com.example.access_control.AccessControl.NetSDKDemo.HCNetSDK;
import com.example.access_control.entity.AccessControl;
import com.example.access_control.entity.AccessControlLog;
import com.example.access_control.mapper.AccessControlMapper;
import com.example.access_control.service.AccessControlLogService;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.ptr.IntByReference;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.json.JSONException;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
@Data
@Configuration
@ConfigurationProperties(prefix = "hkaccesscontrol")
public class AccessControlInit {

    public static int lUserID = -1;//用户句柄
    public static HCNetSDK hCNetSDK = null;

    @Resource
    public AccessControlMapper accessControlMapper;
    @Resource
    public AccessControlLogService accessControlLogService;

    // 存放所有设备的句柄
    public Map<Integer, Object> accessControlMap = new HashMap<Integer, Object>();

    /**
     * Windows
     */
    private String libpath_win;
    /**
     * linux
     */
    private String libpath_linux;

    private boolean createSDKInstance() {
        if (hCNetSDK == null) {
            synchronized (HCNetSDK.class) {
                String strDllPath = "";
                try {
                    //System.setProperty("jna.debug_load", "true");
                    if (osSelect.isWindows())
                        //win系统加载库路径
//                        strDllPath = System.getProperty("user.dir") + "\\libs\\AccessControl\\win\\HCNetSDK.dll";
                        strDllPath = libpath_win;
                    else if (osSelect.isLinux())
                        //Linux系统加载库路径
//                        strDllPath = System.getProperty("user.dir") + "/libs/AccessControl/linux/libhcnetsdk.so";
                        strDllPath = libpath_linux;
                    hCNetSDK = (HCNetSDK) Native.loadLibrary(strDllPath, HCNetSDK.class);
                } catch (Exception ex) {
                    System.out.println("loadLibrary: " + strDllPath + " Error: " + ex.getMessage());
                    return false;
                }
            }
        }
        return true;
    }

    @Bean
    public boolean initHKSDK() {
//        if (hCNetSDK == null) {
        new Thread(() -> {
            List<AccessControl> accessControlList = accessControlMapper.selectList(null);
            log.info("初始化海康SDK");
            for (AccessControl accessControl : accessControlList) {
                if (!createSDKInstance()) {
                    System.out.println("Load SDK fail");
                    continue;
                }
                //linux系统建议调用以下接口加载组件库
                if (osSelect.isLinux()) {
                    HCNetSDK.BYTE_ARRAY ptrByteArray1 = new HCNetSDK.BYTE_ARRAY(256);
                    HCNetSDK.BYTE_ARRAY ptrByteArray2 = new HCNetSDK.BYTE_ARRAY(256);
                    //这里是库的绝对路径，请根据实际情况修改，注意改路径必须有访问权限
                    String strPath1 = System.getProperty("user.dir") + "/lib/libcrypto.so.1.1";
                    String strPath2 = System.getProperty("user.dir") + "/lib/libssl.so.1.1";
                    System.arraycopy(strPath1.getBytes(), 0, ptrByteArray1.byValue, 0, strPath1.length());
                    ptrByteArray1.write();
                    hCNetSDK.NET_DVR_SetSDKInitCfg(HCNetSDK.NET_SDK_INIT_CFG_LIBEAY_PATH, ptrByteArray1.getPointer());
                    System.arraycopy(strPath2.getBytes(), 0, ptrByteArray2.byValue, 0, strPath2.length());
                    ptrByteArray2.write();
                    hCNetSDK.NET_DVR_SetSDKInitCfg(HCNetSDK.NET_SDK_INIT_CFG_SSLEAY_PATH, ptrByteArray2.getPointer());
                    String strPathCom = System.getProperty("user.dir") + "/lib/";
                    HCNetSDK.NET_DVR_LOCAL_SDK_PATH struComPath = new HCNetSDK.NET_DVR_LOCAL_SDK_PATH();
                    System.arraycopy(strPathCom.getBytes(), 0, struComPath.sPath, 0, strPathCom.length());
                    struComPath.write();
                    hCNetSDK.NET_DVR_SetSDKInitCfg(HCNetSDK.NET_SDK_INIT_CFG_SDK_PATH, struComPath.getPointer());
                }
                //SDK初始化，和进程保持同步，仅需要调用一次
                hCNetSDK.NET_DVR_Init();
                //开启SDK日志打印
//                hCNetSDK.NET_DVR_SetLogToFile(3, "./sdklog", false);
                //设备登录
                lUserID = loginDevice(accessControl.getIp(), (short) Integer.parseInt(accessControl.getPort()), accessControl.getUser(), accessControl.getPassword());    //登陆设备
//            lUserID = loginDevice("192.168.6.103", (short) 8000, "admin", "zxkj1234560.");    //登陆设备
                if (lUserID == -1) {
                    log.error(accessControl.getAccessControlName() + "登录设备失败，错误码为: " + hCNetSDK.NET_DVR_GetLastError());
                    continue;
                } else {
                    Map<String, Object> map = new HashMap<>();
                    map.put("hCNetSDK", hCNetSDK);
                    map.put("lUserID", lUserID);
                    accessControlMap.put(accessControl.getId(), map);
                    // 修改在线状态
                    accessControl.setOnlineStatus(1);
                    accessControlMapper.updateById(accessControl);
                    log.info(accessControl.getAccessControlName() + "登录设备成功，用户句柄：" + lUserID);
                }
            }
            log.info("初始化海康SDK已完毕");
        }).start();

        return true;
    }

    /**
     * 登录设备，支持 V40 和 V30 版本，功能一致。
     *
     * @param ip   设备IP地址
     * @param port SDK端口，默认为设备的8000端口
     * @param user 设备用户名
     * @param psw  设备密码
     * @return 登录成功返回用户ID，失败返回-1
     */
    public static int loginDevice(String ip, short port, String user, String psw) {
        // 创建设备登录信息和设备信息对象
        HCNetSDK.NET_DVR_USER_LOGIN_INFO loginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
        HCNetSDK.NET_DVR_DEVICEINFO_V40 deviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();

        // 设置设备IP地址
        byte[] deviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
        byte[] ipBytes = ip.getBytes();
        System.arraycopy(ipBytes, 0, deviceAddress, 0, Math.min(ipBytes.length, deviceAddress.length));
        loginInfo.sDeviceAddress = deviceAddress;

        // 设置用户名和密码
        byte[] userName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
        byte[] password = psw.getBytes();
        System.arraycopy(user.getBytes(), 0, userName, 0, Math.min(user.length(), userName.length));
        System.arraycopy(password, 0, loginInfo.sPassword, 0, Math.min(password.length, loginInfo.sPassword.length));
        loginInfo.sUserName = userName;

        // 设置端口和登录模式
        loginInfo.wPort = port;
        loginInfo.bUseAsynLogin = false; // 同步登录
        loginInfo.byLoginMode = 0; // 使用SDK私有协议

        // 执行登录操作
        int userID = hCNetSDK.NET_DVR_Login_V40(loginInfo, deviceInfo);
        if (userID == -1) {
//            log.error("登录失败，错误码为: " + hCNetSDK.NET_DVR_GetLastError());
        } else {
            System.out.println(ip + " 设备登录成功！");
            // 处理通道号逻辑
//			int startDChan = deviceInfo.struDeviceV30.byStartDChan;
//			System.out.println("预览起始通道号: " + startDChan);
        }
        return userID; // 返回登录结果
    }

    /**
     * 远程控门
     */
    public void remoteControlGate(int accessControlId, int dwStaic) {
//        initHKSDK(accessControl);
        Map<String, Object> connectionMap = (Map<String, Object>) accessControlMap.get(accessControlId);
        hCNetSDK = (HCNetSDK) connectionMap.get("hCNetSDK");
        lUserID = (int) connectionMap.get("lUserID");
        /**第二个参数lGatewayIndex
         [in] 门禁序号（楼层编号、锁ID），从1开始，-1表示对所有门（或者梯控的所有楼层）进行操作
         第三个参数dwStaic
         [in] 命令值：0- 关闭（对于梯控，表示受控），1- 打开（对于梯控，表示开门），2- 常开（对于梯控，表示自由、通道状态），3- 常关（对于梯控，表示禁用），4- 恢复（梯控，普通状态），5- 访客呼梯（梯控），6- 住户呼梯（梯控）*/
        boolean b_gate = hCNetSDK.NET_DVR_ControlGateway(lUserID, 1, dwStaic);
        if (b_gate == false) {
            System.out.println("远程控门失败,err=" + hCNetSDK.NET_DVR_GetLastError());
            return;
        }
        System.out.println("远程控门成功");
        return;
    }

    /**
     * 设置语音播报
     */
    public void setVoice(int accessControlId, int switchStatus) {
        Map<String, Object> connectionMap = (Map<String, Object>) accessControlMap.get(accessControlId);
        hCNetSDK = (HCNetSDK) connectionMap.get("hCNetSDK");
        lUserID = (int) connectionMap.get("lUserID");
        // 获取门禁主机参数
        HCNetSDK.NET_DVR_ACS_CFG struAcsCfg = new HCNetSDK.NET_DVR_ACS_CFG();
        struAcsCfg.dwSize = struAcsCfg.size();
        /**设置门禁主机参数*/
        struAcsCfg.byShowCardNo = 1;     //开启显示卡号
        struAcsCfg.byVoicePrompt = (byte) switchStatus;    //开启语音提示
        struAcsCfg.byUploadCapPic = 1;   //开启联动抓图后，设备上抓拍的图片才会通过报警布防上传，否则没有不上传
        struAcsCfg.byShowCapPic = 1;
        struAcsCfg.write();
        boolean b_SetAcsCfg = hCNetSDK.NET_DVR_SetDVRConfig(lUserID, HCNetSDK.NET_DVR_SET_ACS_CFG, 0xFFFFFFFF, struAcsCfg.getPointer(), struAcsCfg.size());
        if (b_SetAcsCfg = false) {
            System.out.println("设置门禁主机参数，错误码为：" + hCNetSDK.NET_DVR_GetLastError());
            return;
        } else {
            System.out.println("设置门禁主机参数成功！！！");
        }

    }

    /**
     * 插入用户
     */
    public String insertUser(JSONObject data) throws Exception {
        Map<String, Object> connectionMap = (Map<String, Object>) accessControlMap.get(data.getInt("accessControlId"));
        hCNetSDK = (HCNetSDK) connectionMap.get("hCNetSDK");
        lUserID = (int) connectionMap.get("lUserID");

        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024);    //数组
        String strInBuffer = "POST /ISAPI/AccessControl/UserInfo/Record?format=json"; //此URL也是下发人员
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();
        int lHandler = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_JSON_CONFIG, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
        if (lHandler < 0) {
            System.out.println("AddUserInfo NET_DVR_StartRemoteConfig 失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return "error";
        } else {
            System.out.println("AddUserInfo NET_DVR_StartRemoteConfig 成功!");
            //输入参数，XML或者JSON数据,下发人员信息json报文,其他参数设置参考conf/acs/AddUserInfoParam.json中报文参数
//            Map<String, Object> parameter = new HashMap<>();
//            parameter.put("employeeNo", data.getStr("employeeNo")); // 员工ID
//            parameter.put("name", data.getStr("name")); // 员工名称
//            parameter.put("enable", data.getBool("enable")); // 是否启用
//            parameter.put("doorNo", data.getStr("doorNo")); // 门编号
//            String input = ConfigFileUtil.getReqBodyFromTemplate("static/templates/AddUserInfoParam.json", parameter);
            String input = String.format("{\n" +
                    "  \"UserInfo\":{\n" +
                    "    \"employeeNo\": \"%s\",\n" +
                    "    \"name\": \"%s\",\n" +
                    "    \"userType\":\"normal\",\n" +
                    "    \"Valid\":{\n" +
                    "      \"enable\": %s,\n" +
                    "      \"beginTime\":\"2023-01-01T00:00:00\",\n" +
                    "      \"endTime\":\"2033-12-30T23:59:59\",\n" +
                    "      \"timeType\":\"local\"\n" +
                    "    },\n" +
                    "    \"doorRight\":\"1\",\n" +
                    "    \"RightPlan\":[\n" +
                    "      {\n" +
                    "        \"doorNo\": %s,\n" +
                    "        \"planTemplateNo\":\"1\"\n" +
                    "      }\n" +
                    "    ],\n" +
                    "    \"gender\":\"male\",\n" +
                    "    \"localUIRight\":false\n" +
                    "  }\n" +
                    "}", data.getStr("employeeNo"), data.getStr("name"), data.getBool("enable"), data.getInt("doorNo"));
            System.out.println("下发人员参数：" + input);

            byte[] byInbuffer = input.getBytes("utf-8");
            int iInBufLen = byInbuffer.length;

            HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(iInBufLen);
            ptrInBuffer.read();
            System.arraycopy(byInbuffer, 0, ptrInBuffer.byValue, 0, iInBufLen);
            ptrInBuffer.write();

            HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(1024);
//            Pointer ptr =new PointerByReference()
            IntByReference pInt = new IntByReference(0);
            org.json.JSONObject jsonResult = null;
            while (true) {
                int dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, ptrInBuffer.getPointer(), iInBufLen, ptrOutuff.getPointer(), 1024, pInt);
                if (dwState == -1) {
                    System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
                    break;
                }
                //读取返回的json并解析
                ptrOutuff.read();
                String strResult = new String(ptrOutuff.byValue).trim();
                System.out.println("dwState:" + dwState + ",strResult:" + strResult);

                jsonResult = new org.json.JSONObject(strResult);
                int statusCode = jsonResult.getInt("statusCode");
                String statusString = jsonResult.getString("statusString");
                if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) {
                    System.out.println("配置等待");
                    Thread.sleep(10);
                    continue;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                    System.out.println("下发人员失败, json retun:" + jsonResult.toString());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                    System.out.println("下发人员异常, json retun:" + jsonResult.toString());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {//返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了，但并不代表下发成功，比如有些设备可能因为人员已存在等原因下发失败，所以需要解析Json报文
                    if (statusCode != 1) {
                        System.out.println("下发人员成功,但是有异常情况:" + jsonResult.toString());
                    } else {
                        System.out.println("下发人员成功: json retun:" + jsonResult.toString());
                    }
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                    //下发人员时：dwState其实不会走到这里，因为设备不知道我们会下发多少个人，所以长连接需要我们主动关闭
                    System.out.println("下发人员完成");
                    break;
                }
            }
            if (!hCNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                System.out.println("NET_DVR_StopRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
            } else {
                System.out.println("NET_DVR_StopRemoteConfig接口成功");
            }
            return jsonResult.get("statusString").toString();
        }
    }

    public static String put_isapi(int lUserID, String url, String inputXml, HCNetSDK hCNetSDK) {
        HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
        struXMLInput.read();
        HCNetSDK.BYTE_ARRAY stringRequest = new HCNetSDK.BYTE_ARRAY(1024);
        stringRequest.read();
        //输入ISAPI协议命令
        System.arraycopy(url.getBytes(), 0, stringRequest.byValue, 0, url.length());
        stringRequest.write();
        struXMLInput.dwSize = struXMLInput.size();
        struXMLInput.lpRequestUrl = stringRequest.getPointer();
        struXMLInput.dwRequestUrlLen = url.length();
        HCNetSDK.BYTE_ARRAY ptrInBuffer = new HCNetSDK.BYTE_ARRAY(inputXml.length());
        ptrInBuffer.read();
        try {
            System.arraycopy(inputXml.getBytes("utf-8"), 0, ptrInBuffer.byValue, 0, inputXml.length());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        ptrInBuffer.write();
        struXMLInput.lpInBuffer = ptrInBuffer.getPointer();
        struXMLInput.dwInBufferSize = inputXml.length();
        struXMLInput.write();
        //输出缓冲区大小，可以依据事件输出报文大小进行调整
        HCNetSDK.BYTE_ARRAY stringXMLOut = new HCNetSDK.BYTE_ARRAY(2 * 1024 * 1024);
        stringXMLOut.read();
        HCNetSDK.BYTE_ARRAY struXMLStatus = new HCNetSDK.BYTE_ARRAY(1024);
        struXMLStatus.read();
        HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT struXMLOutput = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
        struXMLOutput.read();
        struXMLOutput.dwSize = struXMLOutput.size();
        struXMLOutput.lpOutBuffer = stringXMLOut.getPointer();
        struXMLOutput.dwOutBufferSize = stringXMLOut.size();
        struXMLOutput.lpStatusBuffer = struXMLStatus.getPointer();
        struXMLOutput.dwStatusSize = struXMLStatus.size();
        struXMLOutput.write();
        if (!hCNetSDK.NET_DVR_STDXMLConfig(lUserID, struXMLInput, struXMLOutput)) {
            int iErr = hCNetSDK.NET_DVR_GetLastError();
            System.err.println("NET_DVR_STDXMLConfig失败，错误号" + iErr + "----URL:" + url);
            return null;
        } else {
            stringXMLOut.read();
            System.out.println("输出文本大小：" + struXMLOutput.dwReturnedXMLSize);
            //打印输出XML文本
            String strOutXML = new String(stringXMLOut.byValue).trim();
            struXMLStatus.read();
            String strStatus = new String(struXMLStatus.byValue).trim();
            return strOutXML;
        }
    }

    public static String get_isapi(int lUserID, String url, HCNetSDK hCNetSDK) {
        HCNetSDK.NET_DVR_XML_CONFIG_INPUT struXMLInput = new HCNetSDK.NET_DVR_XML_CONFIG_INPUT();
        struXMLInput.read();
        HCNetSDK.BYTE_ARRAY stringRequest = new HCNetSDK.BYTE_ARRAY(1024);
        stringRequest.read();
        //输入ISAPI协议命令
        System.arraycopy(url.getBytes(), 0, stringRequest.byValue, 0, url.length());
        stringRequest.write();
        struXMLInput.dwSize = struXMLInput.size();
        struXMLInput.lpRequestUrl = stringRequest.getPointer();
        struXMLInput.dwRequestUrlLen = url.length();
        struXMLInput.lpInBuffer = null;
        struXMLInput.dwInBufferSize = 0;
        struXMLInput.write();

        HCNetSDK.BYTE_ARRAY stringXMLOut = new HCNetSDK.BYTE_ARRAY(8 * 1024);
        stringXMLOut.read();
        HCNetSDK.BYTE_ARRAY struXMLStatus = new HCNetSDK.BYTE_ARRAY(1024);
        struXMLStatus.read();
        HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT struXMLOutput = new HCNetSDK.NET_DVR_XML_CONFIG_OUTPUT();
        struXMLOutput.read();
        struXMLOutput.dwSize = struXMLOutput.size();
        struXMLOutput.lpOutBuffer = stringXMLOut.getPointer();
        struXMLOutput.dwOutBufferSize = stringXMLOut.size();
        struXMLOutput.lpStatusBuffer = struXMLStatus.getPointer();
        struXMLOutput.dwStatusSize = struXMLStatus.size();
        struXMLOutput.write();
        if (!hCNetSDK.NET_DVR_STDXMLConfig(lUserID, struXMLInput, struXMLOutput)) {
            int iErr = hCNetSDK.NET_DVR_GetLastError();
            System.err.println("NET_DVR_STDXMLConfig失败，错误号" + iErr + "----URL:" + url);
            return null;
        } else {
            stringXMLOut.read();
            System.out.println("输出文本大小：" + struXMLOutput.dwReturnedXMLSize);
            //打印输出XML文本
            String strOutXML = new String(stringXMLOut.byValue).trim();
            System.out.println(strOutXML);
            struXMLStatus.read();
            String strStatus = new String(struXMLStatus.byValue).trim();
            System.out.println(strStatus);
            return strOutXML;
        }
    }

    /**
     * 删除用户
     */
    public String deleteUser(JSONObject data) throws Exception {
        Map<String, Object> connectionMap = (Map<String, Object>) accessControlMap.get(data.getInt("accessControlId"));
        hCNetSDK = (HCNetSDK) connectionMap.get("hCNetSDK");
        lUserID = (int) connectionMap.get("lUserID");

        String deleteUserjson = String.format("{\n" +
                "  \"UserInfoDetail\": {\n" +
                "    \"mode\":  \"%s\",\n" +
                "    \"EmployeeNoList\": [\n" +
                "      {\n" +
                "        \"employeeNo\":  \"%s\"\n" +
                "      }\n" +
                "    ]\n" +
                "  }\n" +
                "}", data.getStr("mode"), data.getStr("employeeNo"));
        System.out.println("删除人员参数：" + deleteUserjson);
        String deleteUserUrl = "PUT /ISAPI/AccessControl/UserInfoDetail/Delete?format=json";
        String result = put_isapi(lUserID, deleteUserUrl, deleteUserjson, hCNetSDK);
        System.out.println(result);
        //获取删除进度
        String process = "";
        while (true) {
            String getDeleteProcessUrl = "GET /ISAPI/AccessControl/UserInfoDetail/DeleteProcess?format=json";
            String deleteResult = get_isapi(lUserID, getDeleteProcessUrl, hCNetSDK);
            org.json.JSONObject jsonObject = new org.json.JSONObject(deleteResult);
            org.json.JSONObject jsonObject1 = jsonObject.getJSONObject("UserInfoDetailDeleteProcess");
            process = jsonObject1.getString("status");
            System.out.println("process =" + process);
            if (process.equals("processing")) {
                System.out.println("正在删除");
                continue;
            } else if (process.equals("success")) {
                System.out.println("删除成功");
                break;
            } else if (process.equals("failed")) {
                System.out.println("删除失败");
                break;
            }
        }

        return process;
    }

    /**
     * 按URL方式下发人脸图片
     *
     * @throws JSONException
     */
    public void sendFace(JSONObject data) throws JSONException {
        Map<String, Object> connectionMap = (Map<String, Object>) accessControlMap.get(data.getInt("accessControlId"));
        hCNetSDK = (HCNetSDK) connectionMap.get("hCNetSDK");
        lUserID = (int) connectionMap.get("lUserID");

        HCNetSDK.BYTE_ARRAY ptrByteArray = new HCNetSDK.BYTE_ARRAY(1024);    //数组
        String strInBuffer = "PUT /ISAPI/Intelligent/FDLib/FDSetUp?format=json";
        System.arraycopy(strInBuffer.getBytes(), 0, ptrByteArray.byValue, 0, strInBuffer.length());//字符串拷贝到数组中
        ptrByteArray.write();
        int lHandler = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_FACE_DATA_RECORD, ptrByteArray.getPointer(), strInBuffer.length(), null, null);
        if (lHandler < 0) {
            System.out.println("Addface NET_DVR_StartRemoteConfig 失败,错误码为" + hCNetSDK.NET_DVR_GetLastError());
            return;
        } else {
            System.out.println("Addface NET_DVR_StartRemoteConfig 成功!");

            HCNetSDK.NET_DVR_JSON_DATA_CFG struAddFaceDataCfg = new HCNetSDK.NET_DVR_JSON_DATA_CFG();
            struAddFaceDataCfg.read();

            org.json.JSONObject jsonObject = new org.json.JSONObject();
            jsonObject.put("faceURL", "http://192.168.6.104:9002/img/1111.jpg"); //人脸图片URL,平台自己实现，需要保证设备可以正常访问
//            jsonObject.put("faceURL", data.getStr("faceURL")); //人脸图片URL,平台自己实现，需要保证设备可以正常访问
            jsonObject.put("faceLibType", "blackFD");
            jsonObject.put("FDID", "1");
            jsonObject.put("FPID", data.getStr("employeeNo"));//人脸下发关联的工号

            String strJsonData = jsonObject.toString();
            System.arraycopy(strJsonData.getBytes(), 0, ptrByteArray.byValue, 0, strJsonData.length());//字符串拷贝到数组中
            ptrByteArray.write();
            struAddFaceDataCfg.dwSize = struAddFaceDataCfg.size();
            struAddFaceDataCfg.lpJsonData = ptrByteArray.getPointer();
            struAddFaceDataCfg.dwJsonDataSize = strJsonData.length();
            struAddFaceDataCfg.lpPicData = null;
            struAddFaceDataCfg.dwPicDataSize = 0;
            struAddFaceDataCfg.write();
            HCNetSDK.BYTE_ARRAY ptrOutuff = new HCNetSDK.BYTE_ARRAY(1024);

            IntByReference pInt = new IntByReference(0);

            while (true) {
                int dwState = hCNetSDK.NET_DVR_SendWithRecvRemoteConfig(lHandler, struAddFaceDataCfg.getPointer(), struAddFaceDataCfg.dwSize, ptrOutuff.getPointer(), 1024, pInt);
                log.info("状态码：{}", dwState);

                if (dwState == -1) {
                    System.out.println("NET_DVR_SendWithRecvRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
                    break;
                }
                //读取返回的json并解析
                ptrOutuff.read();
                String strResult = new String(ptrOutuff.byValue).trim();
                System.out.println("dwState:" + dwState + ",strResult:" + strResult);

                org.json.JSONObject jsonResult = new org.json.JSONObject(strResult);
                int statusCode = jsonResult.getInt("statusCode");
                String statusString = jsonResult.getString("statusString");
                if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_NEED_WAIT) {
                    System.out.println("配置等待");
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    continue;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FAILED) {
                    System.out.println("下发人脸失败, json retun:" + jsonResult.toString());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_EXCEPTION) {
                    System.out.println("下发人脸异常, json retun:" + jsonResult.toString());
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_SUCCESS) {//返回NET_SDK_CONFIG_STATUS_SUCCESS代表流程走通了，但并不代表下发成功，比如人脸图片不符合设备规范等原因，所以需要解析Json报文
                    if (statusCode != 1) {
                        System.out.println("下发人脸成功,但是有异常情况:" + jsonResult.toString());
                    } else {
                        System.out.println("下发人脸成功,  json retun:" + jsonResult.toString());
                    }
                    break;
                } else if (dwState == HCNetSDK.NET_SDK_CONFIG_STATUS_FINISH) {
                    //下发人脸时：dwState其实不会走到这里，因为设备不知道我们会下发多少个人，所以长连接需要我们主动关闭
                    System.out.println("下发人脸完成");
                    break;
                }
            }
            if (!hCNetSDK.NET_DVR_StopRemoteConfig(lHandler)) {
                System.out.println("NET_DVR_StopRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
            } else {
                System.out.println("NET_DVR_StopRemoteConfig接口成功");
            }
        }
    }

    /**
     * 门禁事件查询，基于起止时间，事件类型进行查询
     * logType  日志类型1人脸识别2刷卡识别3远程开门4远程关门5远程常开6远程常闭
     *
     * @throws InterruptedException
     */
    public List<AccessControlLog> searchAllEvent(Map<String, Object> paramsMap,int dwMajor,int dwMinor,int logType) throws InterruptedException {
        Map<String, Object> connectionMap = (Map<String, Object>) accessControlMap.get(Convert.toInt(paramsMap.get("accessControlId")));
        hCNetSDK = (HCNetSDK) connectionMap.get("hCNetSDK");
        lUserID = (int) connectionMap.get("lUserID");

        int i = 0; //事件条数
        HCNetSDK.NET_DVR_ACS_EVENT_COND struAcsEventCond = new HCNetSDK.NET_DVR_ACS_EVENT_COND();
        struAcsEventCond.read();
        struAcsEventCond.dwSize = struAcsEventCond.size();
        //查询全部主次类型的报警
//        struAcsEventCond.dwMajor = 5; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 75; //

        // 远程开门事件
//        struAcsEventCond.dwMajor = 3; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 1024; //
        // 远程关门事件
//        struAcsEventCond.dwMajor = 3; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 1025; //
        // 管理员登录设置界面事件
//        struAcsEventCond.dwMajor = 3; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 80; //
        // 远程控门常开事件
//        struAcsEventCond.dwMajor = 3; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 1026; //
//       // 远程控门常闭事件
//        struAcsEventCond.dwMajor = 3; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 1027; //
        // 门禁卡认证通过
//        struAcsEventCond.dwMajor = 5; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 1; //
        // 人脸识别成功
//        struAcsEventCond.dwMajor = 5; // 主次事件类型设为0，代表查询所有事件
//        struAcsEventCond.dwMinor = 75; //

        struAcsEventCond.dwMajor = dwMajor; // 主次事件类型设为0，代表查询所有事件
        struAcsEventCond.dwMinor = dwMinor; //

        //开始时间
        struAcsEventCond.struStartTime.dwYear = Convert.toInt(paramsMap.get("offsetYear"));
        struAcsEventCond.struStartTime.dwMonth = Convert.toInt(paramsMap.get("offsetMonth"));
        struAcsEventCond.struStartTime.dwDay = Convert.toInt(paramsMap.get("offsetDay"));
        struAcsEventCond.struStartTime.dwHour = Convert.toInt(paramsMap.get("offsetHour"));
        struAcsEventCond.struStartTime.dwMinute = Convert.toInt(paramsMap.get("offsetMinute"));
        struAcsEventCond.struStartTime.dwSecond = Convert.toInt(paramsMap.get("offsetSecond"));
        //结束时间
        struAcsEventCond.struEndTime.dwYear = Convert.toInt(paramsMap.get("year"));
        struAcsEventCond.struEndTime.dwMonth = Convert.toInt(paramsMap.get("month"));
        struAcsEventCond.struEndTime.dwDay = Convert.toInt(paramsMap.get("day"));
        struAcsEventCond.struEndTime.dwHour = Convert.toInt(paramsMap.get("hour"));
        struAcsEventCond.struEndTime.dwMinute = Convert.toInt(paramsMap.get("minute"));
        struAcsEventCond.struEndTime.dwSecond = Convert.toInt(paramsMap.get("second"));
        struAcsEventCond.wInductiveEventType = 1;
        struAcsEventCond.byPicEnable = 1; //是否带图片，0-不带图片，1-带图片
        struAcsEventCond.write();
        Pointer ptrStruEventCond = struAcsEventCond.getPointer();
        int m_lSearchEventHandle = hCNetSDK.NET_DVR_StartRemoteConfig(lUserID, HCNetSDK.NET_DVR_GET_ACS_EVENT, ptrStruEventCond, struAcsEventCond.size(), null, null);
        if (m_lSearchEventHandle <= -1) {
            System.out.println("NET_DVR_StartRemoteConfig调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
        }
        HCNetSDK.NET_DVR_ACS_EVENT_CFG struAcsEventCfg = new HCNetSDK.NET_DVR_ACS_EVENT_CFG();
        struAcsEventCfg.read();
        struAcsEventCfg.dwSize = struAcsEventCfg.size();
        struAcsEventCfg.write();
        Pointer ptrStruEventCfg = struAcsEventCfg.getPointer();
        List<AccessControlLog> accessControlLogList = new ArrayList<>();
        while (true) {
            System.out.println("i=" + i);
            int dwEventSearch = hCNetSDK.NET_DVR_GetNextRemoteConfig(m_lSearchEventHandle, ptrStruEventCfg, struAcsEventCfg.size());
            if (dwEventSearch <= -1) {
                System.out.println("NET_DVR_GetNextRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
            }
            if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_NEED_WAIT) {
                System.out.println("配置等待....");
                Thread.sleep(10);
                continue;
            } else if (dwEventSearch == HCNetSDK.NET_SDK_NEXT_STATUS__FINISH) {
                System.out.println("获取事件完成");
                break;
            } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_FAILED) {
                System.out.println("获取事件出现异常");
                break;
            } else if (dwEventSearch == HCNetSDK.NET_SDK_GET_NEXT_STATUS_SUCCESS) {
                System.out.println("打印开始~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");

                struAcsEventCfg.read();
                //获取的事件信息通过struAcsEventCfg结构体进行解析，
                System.out.println(i + "获取事件成功, 报警主类型：" + Integer.toHexString(struAcsEventCfg.dwMajor) + " 报警次类型：" + Integer.toHexString(struAcsEventCfg.dwMinor) + " 卡号：" + new String(struAcsEventCfg.struAcsEventInfo.byCardNo).trim());
                /**
                 * 工号有两个字段，dwEmployeeNo表示工号，当值为0时，表示无效，解析byEmployeeNo参数
                 */
                System.out.println("工号1：" + struAcsEventCfg.struAcsEventInfo.dwEmployeeNo);
//                System.out.println("工号2：" + new String(struAcsEventCfg.struAcsEventInfo.byEmployeeNo));
                //口罩功能，需要设备支持此功能 0-保留，1-未知，2-不戴口罩，3-戴口罩
                System.out.println("是否带口罩:" + struAcsEventCfg.struAcsEventInfo.byMask);
                System.out.println("时间时间:" + struAcsEventCfg.struTime.dwYear + " 年 " + struAcsEventCfg.struTime.dwMonth + " 月 " + struAcsEventCfg.struTime.dwDay +
                        " 日 " + struAcsEventCfg.struTime.dwHour + " 时 " + struAcsEventCfg.struTime.dwMinute + " 分 " + struAcsEventCfg.struTime.dwSecond + " 秒");
//                System.out.println("刷卡信息：" + new String(struAcsEventCfg.struAcsEventInfo.byCardNo));
                System.out.println("事件流水号：" + struAcsEventCfg.struAcsEventInfo.dwSerialNo);
                System.out.println("人员类型：" + struAcsEventCfg.struAcsEventInfo.byUserType);
                System.out.println("当前验证模式：" + struAcsEventCfg.struAcsEventInfo.byCurrentVerifyMode);

                //人脸图片保存
                if (struAcsEventCfg.dwPicDataLen > 0 || struAcsEventCfg.pPicData != null) {
                    FileOutputStream fout;
                    try {
                        /**
                         * 人脸图片保存路径
                         */
                        String filename = ".\\pic\\" + i + "_event.jpg";
                        fout = new FileOutputStream(filename);
                        //将字节写入文件
                        long offset = 0;
                        ByteBuffer buffers = struAcsEventCfg.pPicData.getByteBuffer(offset, struAcsEventCfg.dwPicDataLen);
                        byte[] bytes = new byte[struAcsEventCfg.dwPicDataLen];
                        buffers.rewind();
                        buffers.get(bytes);
                        fout.write(bytes);
                        fout.close();
                    } catch (FileNotFoundException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println("打印结束~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
                i++;
                String time = String.format("%d-%02d-%02d %02d:%02d:%02d", struAcsEventCfg.struTime.dwYear, struAcsEventCfg.struTime.dwMonth, struAcsEventCfg.struTime.dwDay,
                        struAcsEventCfg.struTime.dwHour, struAcsEventCfg.struTime.dwMinute, struAcsEventCfg.struTime.dwSecond);
                // 组织数据
                List<AccessControlLog> dbAccessControlLogList = accessControlLogService.list(new QueryWrapper<AccessControlLog>().ge("create_time", Convert.toStr(paramsMap.get("offsetDate")))
                        .le("create_time", Convert.toStr(paramsMap.get("date"))).eq("log_type",logType));
                if (!dbAccessControlLogList.isEmpty()) {
                    boolean flag = false;
                    for (AccessControlLog dbAccessControlLog : dbAccessControlLogList) {
                        int accessControlId = dbAccessControlLog.getAccessControlId();
                        int userId = dbAccessControlLog.getUserId();
                        String createTime = dbAccessControlLog.getCreateTime();
                        if (accessControlId == Convert.toInt(paramsMap.get("accessControlId"))
                                && userId == struAcsEventCfg.struAcsEventInfo.dwEmployeeNo && createTime.equals(time)) {
                            flag = true;
                            break;
                        }
                    }
                    if (!flag) {
                        AccessControlLog accessControlLog = new AccessControlLog();
                        accessControlLog.setAccessControlId(Convert.toInt(paramsMap.get("accessControlId")));
                        accessControlLog.setUserId(struAcsEventCfg.struAcsEventInfo.dwEmployeeNo);
                        accessControlLog.setLogType(logType);
                        accessControlLog.setCreateTime(time);
                        accessControlLogList.add(accessControlLog);
                    }
                }else {
                    AccessControlLog accessControlLog = new AccessControlLog();
                    accessControlLog.setAccessControlId(Convert.toInt(paramsMap.get("accessControlId")));
                    accessControlLog.setUserId(struAcsEventCfg.struAcsEventInfo.dwEmployeeNo);
                    accessControlLog.setLogType(logType);
                    accessControlLog.setCreateTime(time);
                    accessControlLogList.add(accessControlLog);
                }
            }
        }
        if (!hCNetSDK.NET_DVR_StopRemoteConfig(m_lSearchEventHandle)) {
            System.out.println("NET_DVR_StopRemoteConfig接口调用失败，错误码：" + hCNetSDK.NET_DVR_GetLastError());
        } else {
            System.out.println("NET_DVR_StopRemoteConfig接口成功");
        }
        return accessControlLogList;
    }


}
